home *** CD-ROM | disk | FTP | other *** search
- {
- Here a program to display files from deLux Paint II (*.LBM files)
- drawings. It uses a PD BGI driver for 320x200x256 color mode. Other
- drivers can also be used. Otherwise look in the SWAG lib for routines to
- enter this graphics mode and set a pixel in a certain color.
-
- Code isn't optimal and can be made much faster but works. It doesn't
- display some brushes because of some undocumented sections in the LBM
- file. If the defines are made active the file is decoded and dumped
- textual to the screen. After the program a part of a small PD text file
- I found and used as base for this program. It contained some bugs but
- one evening works does a lot.
-
- Btw. Does anybody know how to distinguish deLux Paint II and deLux Paint
- II Enhanced files?
- }
-
- {---------------------------------------------------------}
- { Written by : Ir. G.W. van der Vegt }
- { Purpose : a Delux Paint II LBM file displayer/decoder}
- { displays 16 and 256 color bitmaps but no }
- { brushes and Delux Paint IIe files yet }
- { }
- { Displays at the moment only }
- { 320x200 or smaller pictures. }
- { }
- { Uses a PD SVGA driver to access MCGA mode. }
- { Substitute your own if you havn't got it. }
- { }
- { File format info by Bob Montgomery 9-21-90, although }
- { it wasn't very accurate (he forgot Motorola swaps }
- { lo & hi byes of words) and didn't cover the }
- { DPPV, CRNG & GRAB sections. }
- { }
- { Use the verbose (and rle) defines to get a dump of the }
- { lbm file. }
- {---------------------------------------------------------}
-
- PROGRAM lbm(INPUT,OUTPUT);
-
- USES
- crt,
- dos,
- graph;
- routines;
-
- { DEFINE verbose}
- { DEFINE rle }
- {$I SVGA256.INC}
-
- TYPE
- rgb = (r,g,b);
- dp2l = ARRAY[0..3] OF BYTE; {read left to right}
- dp2m = ARRAY[1..4] OF CHAR;
- dp2t = ARRAY[rgb] OF BYTE;
- dp2h = RECORD
- msg1 : dp2m; { "FORM" }
- flen : dp2l; { File length - 8 }
- msg2, { "ILBM" }
- msg3 : dp2m; { "BMHD" }
- hlen : dp2l; { Length of header }
- width,
- Length,
- xoff,
- yoff : WORD;
- planes,
- masking,
- compression,
- pad : BYTE;
- tansparent : INTEGER;
- x_aspect,
- y_aspect : BYTE;
- screenwidth,
- screenheight : WORD;
- END;
-
- CONST
- max = 1023;
-
- VAR
- f : FILE;
- dp2 : dp2h;
- msg : dp2m;
- len : dp2l;
- col : dp2t;
-
- i,
- j,
- k,
- y : INTEGER;
- c : BYTE;
- bl,
- h,
- l : LONGINT;
- w : WORD;
- grmode,
- grdriver : INTEGER;
- lin : ARRAY[0..max] OF BYTE;
-
- CONST
- form : dp2m = ('F','O','R','M');
- ilbm : dp2m = ('I','L','B','M');
- bmhd : dp2m = ('B','M','H','D');
- cmap : dp2m = ('C','M','A','P');
- body : dp2m = ('B','O','D','Y');
-
- {$F+}
- FUNCTION Detectvga256 : INTEGER;
-
- BEGIN
- Detectvga256 := svga320x200x256;
- END;
- {$F-}
- FUNCTION Len2long(a : dp2l) : LONGINT;
-
- BEGIN
- Len2long:=(((a[0]*256+a[1])*256+a[2])*256+a[3]);
- END;
-
- FUNCTION Msg2str(a : dp2m) : STRING;
-
- BEGIN
- Msg2str:=a[1]+a[2]+a[3]+a[4];
- END;
-
- FUNCTION Readnext : BYTE;
-
- VAR
- w : WORD;
- c : BYTE;
-
- BEGIN
- Blockread(f,c,1,w);
- IF (w<>1)
- THEN
- BEGIN
- Closegraph;
- Writeln('Unexpected EOF encountered');
- Halt(3);
- END
- ELSE Readnext:=c;
- END;
-
- CONST
- cnt : BYTE = 0;
- rle : BOOLEAN = false;
- dat : BYTE = 0;
- vir : LONGINT = 0;
- rel : LONGINT = 0;
-
- FUNCTION Getnext : BYTE;
-
- VAR
- c : BYTE;
- w : WORD;
-
- BEGIN
- (*
- get a code BYTE from the data stream.
- IF the msb is 1, the 'count' is (1 - code), max = 127. get the next
- BYTE from the data stream, AND REPEAT it 'count' times.
- IF the msb is 0, the 'count' is (1 + code), max = 128. get the next
- 'count' bytes from the data stream.
- *)
- IF (dp2.compression=0)
- THEN Getnext:=Readnext
- ELSE
- IF (cnt=0)
- THEN
- BEGIN
- c:=Readnext;
- rle:=(c>127);
- IF rle
- THEN
- BEGIN
- cnt :=SHORTINT(1-c);
- dat :=Readnext;
- Getnext:=dat;
- {$IFDEF rle}
- Delay(500);
- Writeln;
- Write('RLE : ',byte2hex(c),' = ',cnt:3,'x',byte2hex(dat));
- {$ENDIF}
- END
- ELSE
- BEGIN
- cnt :=1+c;
- dat :=Readnext;
- Getnext:=dat;
- {$IFDEF rle}
- Delay(500);
- Writeln;
- Write('UNC : ',byte2hex(c),' : ',byte2hex(dat));
- {$ENDIF}
- END;
- END
- ELSE
- BEGIN
- IF NOT(rle)
- THEN dat:=Readnext;
- Getnext:=dat;
- {$IFDEF rle}
- IF NOT(rle) THEN Write(' ',byte2hex(dat));
- {$ENDIF}
- END;
-
- Dec(cnt);
- rel:=Filepos(f)-h;
- Inc(vir);
- END;
-
- BEGIN
- Assign(f,Paramstr(1)+'.lbm');
- Reset(f,1);
-
- Blockread(f,dp2,Sizeof(dp2));
-
- WITH dp2 DO
- BEGIN
- {$IFDEF verbose}
- FOR i:=1 TO Sizeof(msg1) DO Write(msg1[i]); Writeln;
- FOR i:=1 TO Sizeof(msg2) DO Write(msg2[i]); Writeln;
- {$ENDIF}
- IF (msg1<>form) OR (msg2<>ilbm) OR (msg3<>bmhd)
- THEN
- BEGIN
- Writeln('No DeLux Paint LBM file.');
- Halt(1);
- END;
-
- {$IFNDEF verbose}
- grdriver:=Installuserdriver('SVGA256',@detectvga256);
- grmode :=svga320x200x256;
- grdriver:=detect;
- Initgraph(grdriver,grmode,'');
- {$ENDIF}
-
- {----Low & high words/bytes are swapped (Motorola 680x0 convention)}
- {$IFDEF verbose}
- Writeln('filelength : ',Len2long(flen));
- Writeln('headlength : ',Len2long(hlen));
- {$ENDIF}
-
- {----Low & high bytes are swapped (Motorola 680x0 convention)}
- width :=Swap(width);
- Length :=Swap(Length);
- xoff :=Swap(xoff);
- yoff :=Swap(yoff);
- screenwidth :=Swap(screenwidth);
- screenheight:=Swap(screenheight);
-
- {$IFDEF verbose}
- Writeln('W .L : ',width ,'x',Length);
- Writeln('Xo.Yo : ',xoff ,'x',yoff );
- Writeln('Xa.Ya : ',x_aspect ,'x',y_aspect);
- Writeln('W. H : ',screenwidth,'x',screenheight);
- Writeln('Planes: ',planes);
- Writeln('Pad : ',pad);
- {$ENDIF}
-
- Blockread(f,msg,Sizeof(msg));
- Blockread(f,len,Sizeof(len));
-
- {$IFDEF verbose}
- Writeln(Msg2str(msg));
- Delay(1000);
- {$ENDIF}
-
- IF (msg=cmap)
- THEN
- BEGIN
- l:=Len2long(len);
- {$IFDEF verbose}
- Writeln('CMAPlen : ',l);
- {$ENDIF}
- FOR i:=1 TO l DIV 3 DO
- BEGIN
- Blockread(f,col,Sizeof(col));
- {$IFDEF verbose}
- Delay(100);
- Writeln(i-1:4,col[r]:4,col[g]:4,col[b]:4);
- {$ELSE}
- Setrgbpalette(i-1,col[r] DIV 4,col[g] DIV 4,col[b] DIV 4);
- {$ENDIF}
- END;
- Blockread(f,msg,Sizeof(msg));
- END;
-
- {----dump unkown sections dppv
- the 4 bytes Length is mostly 104 bytes
- }
- {----dump unkown sections grab
- the 4 bytes Length is 4, section found IN a brush only,
- }
- {----dump 4 unkown sections crng :
- seems each TO consist OF two entries WITH :
- 00 00 0a aa,00 00 01 0e
- 00 00 0a aa,00 00 00 00
- 00 00 0a aa,00 00 00 00
- 00 00 0a aa,00 00 00 00
- brushes contain different values.
- }
- WHILE (msg<>body) DO
- BEGIN
- Blockread(f,len,Sizeof(len));
- l:=Len2long(len);
- Writeln(Msg2str(msg)+' : ',l);
- FOR h:=1 TO l DO
- BEGIN
- Blockread(f,c,1);
- Write(' ',byte2hex(c));
- END;
- Blockread(f,msg,Sizeof(msg));
- Writeln;
- END;
-
- IF (msg=body)
- THEN
- BEGIN
- {$IFDEF verbose}
- Writeln(Msg2str(msg));
- {$ENDIF}
- Blockread(f,len,Sizeof(len));
- l:=Len2long(len);
- h :=Filepos(f);
- {$IFDEF verbose}
- Writeln('BODYlen : ',l);
- {$ENDIF}
- IF compression=0
- THEN bl:=l DIV Length DIV planes
- ELSE bl:=width DIV 8;
- {$IFDEF verbose}
- Writeln('Bytew : ',bl);
- {$ENDIF}
- FOR y:=1 TO Length DO
- BEGIN
- FOR i:=0 TO max DO lin[i]:=0;
- {$R-}
- FOR j:=0 TO planes-1 DO
- FOR i:=0 TO bl-1 DO
- BEGIN
- c:=Getnext;
- FOR k:=0 TO 7 DO
- IF (c AND (128 SHR k))>0
- THEN lin[(i*8)+k]:=lin[(i*8)+k] OR 1 SHL j;
- END;
- {$R+}
- {$IFNDEF verbose}
- FOR i:=1 TO width DO
- Putpixel(i,y,lin[i])
- {$ENDIF}
- END;
-
- END;
-
- {$IFNDEF verbose}
- WHILE NOT Keypressed DO;
- Closegraph;
- {$ELSE}
- Writeln('image ',LONGINT(width)*Length*planes DIV 8);
- Writeln('bodys ',h);
- Writeln('files ',Filesize(f));
- Writeln('filep ',Filepos(f));
- Writeln('heads ',Sizeof(dp2h));
- Writeln('virtu ',vir);
- {$ENDIF}
- Close(f);
- END;
-
- END.
-
- (*
- deluxe paint ii lbm & iff files
-
- the deluxe paint lbm (AND iff) FILE header (40 bytes) has the following
- content:
- struct dp2
- { CHAR msg1[4]; "form"
- BYTE a3, a2, a1, a0; FILE Length - 8 (Read left TO right)
- CHAR msg2[8]; "ilbmbmhd"
- BYTE b3, b2, b1, b0; Length OF header (Read left TO right)
- Int width, Length, xoff, yoff;
- BYTE planes, masking, compression, pad;
- Int tansparent;
- BYTE x_aspect, y_aspect;
- Int screenwidth, screenheight;
- } ;
- there may be a color map following a STRING "cmap" IN the FILE. after cmap
- is the Length OF the color map (4 bytes, Read left TO right). the color
- map is BYTE triples (r, g, b) FOR each colors. the number OF colors is
- 1 shifted left by planes (1 << planes).
- the actual picture data follows a STRING "body" AND Length OF the picture
- data (4 bytes Read left TO right). the picture data is organized on a
- color plane basis FOR dp2, AND on a pixel basis FOR dp2e (enhanced).
- thus, FOR dp2:
- there are (width / 8) bytes per row.
- the data stream FOR each row consists OF all the bytes FOR plane 0,
- followed by all the bytes FOR plane 1, etc.
- AND FOR dp2e:
- there are (width) bytes/row, where each BYTE is a pixel color.
- IF the data is uncomperessed (compression flag = 0), the data stream bytes
- are fed TO the OUTPUT unmodified. IF it is compressed, it is run Length
- encoded as follows:
- get a code BYTE from the data stream.
- IF the msb is 1, the 'count' is (1 - code), max = 127. get the next
- BYTE from the data stream, AND REPEAT it 'count' times.
- IF the msb is 0, the 'count' is (1 + code), max = 128. get the next
- 'count' bytes from the data stream.
- *)